﻿using DataCollection.Core.Models;
using DocumentFormat.OpenXml.Drawing;
using DocumentFormat.OpenXml.Spreadsheet;
using Mapster;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using MQTTnet.Client.Receiving;
using MQTTnet.Exceptions;
using MQTTnet.Protocol;
using MQTTnet.Server;
using Newtonsoft.Json;
using SixLabors.ImageSharp.Drawing;
using SqlSugar.Extensions;
using System.IO.Ports;
using WebSocketSharp;
using WebSocketSharp.Server;

namespace DataCollection.Infrastructure
{
    public class Singleton
    {
        #region 属性

        /// <summary>
        /// 静态对象
        /// </summary>
        private static readonly Lazy<Singleton> _lazyInstance = new Lazy<Singleton>(() => new Singleton());

        /// <summary>
        /// 可用串口
        /// </summary>
        public readonly List<string> SerialPortList = SerialPort.GetPortNames().OrderBy(x => int.Parse(x[3..])).ToList();

        /// <summary>
        /// 系统设置
        /// </summary>
        public SystemSetModel SetModel { get; set; } = null!;

        /// <summary>
        /// Websocket 移动网页需要
        /// </summary>
        private WebSocketServer webSocketServer = null!;

        /// <summary>
        /// 模板信息，移动网页需要
        /// </summary>
        public string TemplateListString = string.Empty;

        /// <summary>
        /// 报告信息，移动网页需要
        /// </summary>
        public string ReportListString = string.Empty;

        /// <summary>
        /// 实时数据 移动网页需要
        /// </summary>
        public Dictionary<string, string> CollectData = new Dictionary<string, string>();

        /// <summary>
        /// 曲线宽度
        /// </summary>
        public int FormsPlotWidth = 0;

        /// <summary>
        /// 曲线高度
        /// </summary>
        public int FormsPlotHeight = 0;

        /// <summary>
        /// 根地址
        /// </summary>
        public static readonly string ReportRootPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CollectReport");

        /// <summary>
        /// 导出地址
        /// </summary>
        public static readonly string ExportPath = "D:\\Program Files (x86)\\Apache24\\htdocs\\Web\\CollectReport";

        #endregion

        #region 自定义方法

        private Singleton() { }

        public static Singleton Instance
        {
            get
            {
                return _lazyInstance.Value;
            }
        }

        /// <summary>
        /// 配置
        /// </summary>
        public void Setup()
        {
            Dictionary<string, Object> where = new Dictionary<string, Object>();
            List<SystemSetModel> list = SqlSugarHelper.Inquireable<SystemSetModel>(where);
            if (list.Count > 0)
            {
                SetModel = list[0];
            }
            else
            {
                SetModel = SystemSetModel.Default();
            }

            ReloadTemplateList();

            ReloadReportList();

            webSocketServer = new WebSocketServer("ws://0.0.0.0:8088");
            webSocketServer.AddWebSocketService<DCWebSocketServer>("/m");
            webSocketServer.Start();

            CollectData.Add("mPressure", "0");
            CollectData.Add("mEnvironmentTemperature", "0");
            CollectData.Add("mBattery", "0");
            CollectData.Add("rPressure", "0");
            CollectData.Add("rEnvironmentTemperature", "0");
            CollectData.Add("rBattery", "0");
        }

        static public void Send()
        { 
            
        }

        public void ReloadTemplateList()
        {
            TemplateListString = TemplateList();
        }

        /// <summary>
        /// 试压模板列表
        /// </summary>
        private string TemplateList()
        {
            Dictionary<string, object> where = new Dictionary<string, object>();
            List<TemplateModel> list = TemplateModel.List(where);
            var newListTyped = list.Select(x => new { x.Number, x.PipePosition, x.DesignPressure }).ToList();
            if (list.Count > 0)
            {
                return JsonConvert.SerializeObject(newListTyped);
            }
            else
            {
                return "";
            }
        }

        public void ReloadReportList()
        {
            ReportListString = ReportList();
        }

        /// <summary>
        /// 加载试压报告
        /// </summary>
        private string ReportList() 
        {
            DirectoryInfo directory = new DirectoryInfo(ExportPath);
            FileInfo[] files = directory.GetFiles();
            List<Report>reportList = new List<Report>();
            foreach (FileInfo file in files) 
            { 
                Report rep = new Report();
                file.Adapt(rep);
                reportList.Add(rep);
            }
            if (reportList.Count > 0)
            {
                return JsonConvert.SerializeObject(reportList);
            }
            else
            {
                return "";
            }
        }

        #endregion
    }

    public class DCWebSocketServer : WebSocketBehavior
    {
        protected override void OnMessage(MessageEventArgs e)
        {
            string msg = "未知异常";
            SocketResponse? backObject = JsonConvert.DeserializeObject<SocketResponse>(e.Data);
            SocketResponse res = new SocketResponse();
            if (backObject is not null)
            {
                if (backObject.code == 2001)
                {
                    res.code = 2001;
                    res.data = JsonConvert.SerializeObject(Singleton.Instance.CollectData);
                    msg = JsonConvert.SerializeObject(res);
                }
                else if (backObject.code == 2002)
                {
                    res.code = 2002;
                    res.data = Singleton.Instance.TemplateListString;
                    msg = JsonConvert.SerializeObject(res);
                }
                else if (backObject.code == 2003)
                {
                    Dictionary<string, object> where = new Dictionary<string, object>();
                    object? obj = backObject.data;
                    if (obj is not null)
                    {
                        string str = (string)obj;
                        where["number"] = str;
                        List<ProjectModel> list = ProjectModel.List(where);
                        res.code = 2003;
                        if (list.Count > 0)
                        {
                            res.data = JsonConvert.SerializeObject(list.First());
                        }
                        else
                        {
                            res.msg = "未查询到试压工程，请核对工程编号！";
                        }
                        msg = JsonConvert.SerializeObject(res);
                    }
                }
                else if (backObject.code == 2004)
                {
                    res.code = 2004;
                    object? obj = backObject.data;
                    if (obj is not null)
                    {
                        string data = (string)obj;
                        ProjectModel? model =   JsonConvert.DeserializeObject<ProjectModel>(data);
                        if (model is not null)
                        {
                            model.TemplateID = long.Parse(model.DesignPressure.ToString());
                            Dictionary<string, object> where = new Dictionary<string, object>();

                            where["number"] = model.TemplateID;
                            List<TemplateModel> templatesList = TemplateModel.List(where);
                            if (templatesList.Count > 0)
                            {
                                model.DesignPressure = templatesList.First().DesignPressure;
                                where["number"] = model.Number;
                                List<ProjectModel> list = ProjectModel.List(where);
                                if (list.Count > 0)
                                {
                                    Log.Debug(string.Format("更新{0}的信息", model.Name));
                                    int update = model.Update();
                                    if (update == 1)
                                    {
                                        res.msg = "编辑成功";
                                    }
                                    else
                                    {
                                        res.msg = "编辑失败";
                                    }
                                }
                                else
                                {
                                    Log.Debug(string.Format("添加{0}的信息", model.Name));
                                    int update = model.Add();
                                    if (update == 1)
                                    {
                                        res.msg = "添加成功";
                                    }
                                    else
                                    {
                                        res.msg = "添加失败";
                                    }
                                }
                            }
                            else
                            {
                                res.msg = "试压模板不存在，请重新选择";
                            }
                        }
                    }
                    msg = JsonConvert.SerializeObject(res);
                }
                else if (backObject.code == 2005)
                {
                    res.code = 2005;
                    res.data = Singleton.Instance.ReportListString;
                    msg = JsonConvert.SerializeObject(res);
                }

                Send(msg);
            }
        }

        protected override void OnError(WebSocketSharp.ErrorEventArgs e)
        {
            Log.Error($"服务器端错误: {e.Message}");

        }

    }

    /// <summary>
    /// 试压报告
    /// </summary>
    public class Report
    {
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; } = null!;

        private string _Directory = null!;

        /// <summary>
        /// 地址
        /// </summary>
        public string Directory
        {
            get
            {
                return System.IO.Path.Combine("\\CollectReport", Name);
            }

            set
            {
                _Directory = value;
            }
        }
    }
}
